#include <fstream>
#include <iostream>
#include <algorithm>
#include <string>
#include <jansson.h>
#include <vector>
#include "video.h"
#include "dbobject.h"
#include "header.h"
#include "log.h"
#include "buffermanager.h"

Video::Video(const std::vector<char>& data, int bounds)
{
	std::string jData(data.data(), bounds);
	json_error_t err;
	mData = json_loads(jData.data(), 0, &err);

	if (!mData) {
		ALOGE("string to json fail: %s\n", err.text);
	}
}

std::vector<char> Video::GetHandleResult()
{
	// const char* cmd = nullptr;
	int cmd;
	int vid = 0;
	int next, batch;

	if (!json_unpack(mData, "{s:i, s?i, s?i, s?i}", "command", &cmd, 
							"vid", &vid,
							"next_batch", &next,
							"batch", &batch)) {
		switch ((Command)cmd) {
			case Command::LS: {
				mResponse = LS();
				break;
			}
			case Command::INFO: {
				mResponse = INFO(vid);
				break;
			}
			case Command::PLAY: {
				mResponse = PLAY(vid);
				break;
			}
			case Command::PLAY_START: {
				return PLAY_START(vid, next, batch);
			}
		}
	}
	std::vector<char> vp(mResponse.begin(), mResponse.end());
	return vp;
}

std::string Video::LS()
{
	std::string ret;

	std::string r;
	std::string err;

	auto allvnames = storage.select(columns(&VideoMetaData::id, &VideoMetaData::name));
	for(auto& item : allvnames) {
		auto& id = std::get<0>(item);
		auto& name = std::get<1>(item);
		r += std::to_string(id);
		r += ". ";
		r += name;
		r += "\n";
	}

	json_t* data = NULL;
	if ((data = json_pack("{s:i, s:s, s:s}", "command", Command::LS,
							"data", r.c_str(),
							"err", err.c_str())))
	{
		ret = json_dumps(data, JSON_COMPACT);
		json_decref(data);
	}
	ALOGD("LS result = %s\n", ret.c_str());

	return ret;
}

std::string Video::INFO(int vid)
{
	std::string ret;
	std::string vname;
	int size;
	std::string err;

	auto metadata = storage.get_pointer<VideoMetaData>(vid);
	if (metadata) {
		vname = metadata->name;
		size = metadata->size;
		err = "OK";
	} else {
		err = "vid invalid";
	}

	json_t* data = NULL;
	if ((data = json_pack("{s:i, s:s, s:i, s:i}", "command", Command::INFO,
							"vname", vname.c_str(),
							"size", size,
							"vid", vid)))
	{
		char* dumps = json_dumps(data, JSON_COMPACT);
		ret = dumps;
		json_decref(data);
		free(dumps);
	}

	return ret;
}

std::string Video::PLAY(int vid)
{
	std::string ret;

	std::string vname;	//文件名
	std::string err;	//错误信息
	uint32_t batch = 0;	//文件分节数

	auto metadata = storage.get_pointer<VideoMetaData>(vid);
	if (metadata) {
		vname = metadata->name;
		batch = metadata->size % BATCH_SIZE ? metadata->size / BATCH_SIZE + 1: metadata->size / BATCH_SIZE;
		err = "OK";
	} else {
		err = "vid invalid";
	}

	json_t* data = NULL;
	if ((data = json_pack("{s:i, s:s, s:s*, s:i, s:i}", "command", Command::PLAY,
					"err", err.c_str(),
					"vname", vname.c_str(),
					"vid", vid,
					"batch", batch)))
	{
		char* dumps = json_dumps(data, JSON_COMPACT);
		ret = dumps;
		json_decref(data);
		free(dumps);
	}

	return ret;
}

std::vector<char> Video::PLAY_START(int vid, int next, int batch)
{
	std::vector<char> ret;
	//在单例，BufferManager中查找vid所在文件是否已经被打开，若打开，获取文件指针。没打开，则令BufferManger打开，缓存在内存中。
	//读取[ptr+(next-1)*1024*1024, ptr+next*1024*1024]范围内的内容
	uint32_t start, count= 0;
	start = (next-1)*(BATCH_SIZE);
	std::unique_ptr<char> buf = BufferManager::getInstance().GetBufferData(vid, start, count);
	//将内容写入data中，组装json
	json_t* body = NULL;
	json_error_t err;
	body = json_pack_ex(&err, 0, "{s:i, s:s, s:i, s:i, s:i}", "command", Command::PLAY_START,
						"err", "OK",
						"vid", vid,
						"next_batch", next,
						"batch", batch);
	if (body) {
		char* dumps = json_dumps(body, JSON_COMPACT);
		mResponse = dumps;
		ret.assign(mResponse.begin(), mResponse.end());
		if (count > 0) {
			ret.insert(ret.end(), buf.get(), buf.get()+count);
		}
		json_decref(body);
		free(dumps);
	} else {
		ALOGD("json_pack error: %s\n", err.text);
	}
    return ret;
}
